using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;


namespace SiRtEt
{
    #region Class : GamePanel
    /// <summary>
	/// Summary description for GamePanel.
	/// </summary>
	public class GamePanel : System.Windows.Forms.UserControl
	{

        // Create an instance of the game logic
		public TheWorld TheGame;

        #region Constructor
        /// <summary>
        /// Constructor: Creates the panels for the game
        /// </summary>
		public GamePanel()
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();

            // Set style of the panels for better graphics performance and reduce flicker
            //-------------------------------------------------
			SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
			SetStyle(ControlStyles.DoubleBuffer, true);          
			SetStyle(ControlStyles.UserPaint, true);
            //-------------------------------------------------

            // Create the game logic
            //------------------------
			TheGame = new TheWorld();
			TheGame.Parent = TheGrid;
			TheGame.Dock = DockStyle.Fill;
            //---------------------------

            // Set up the event handlers for various events in the game logic
            //----------------------------------------
			TheGame.StartGame += new EventHandler(TheGame_StartGame);
			TheGame.NextBlockMade +=new EventHandler(TheGame_NextBlockMade);
			TheGame.NewBlockMade += new EventHandler(TheGame_NewBlockMade);
			TheGame.EndGame += new EventHandler(TheGame_EndGame);
            //----------------------------------------
        }
        #endregion

        #region Disposer
        /// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
        }
        #endregion

        #region Override base control events
        /// <summary>
        /// Does stuff when the control is to be drawn
        /// </summary>
        /// <param name="e"></param>
		protected override void OnPaint(PaintEventArgs e)
		{
			e.Graphics.DrawRectangle(SystemPens.ControlDarkDark,0,0,Width-1,Height-1);
            GameStatus.Text = TheGame.StatusString;
		}

        /// <summary>
        /// Manages the size of the controls when the user changes size
        /// </summary>
        /// <param name="e"></param>
		protected override void OnResize(EventArgs e)
		{
            // Keep setting the size to what we want
            //---------------------------------------
			Width = TheGrid.Width + ControlPanel.Width +4;
			Height = TheGrid.Height+4;

			if(Parent != null)
				Parent.ClientSize = new Size(Width,Height);
            //---------------------------------------

			base.OnResize(e);
			
		}

        /// <summary>
        /// Steps to take at the beginning
        /// </summary>
        /// <param name="e"></param>
		protected override void OnLoad(EventArgs e)
		{
            // Draw the panels
			DrawPanels();
			base.OnLoad(e);
        }
        #endregion

        #region Component Designer generated code

        /// <summary> 
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        private System.Windows.Forms.Panel TheGrid;
        private System.Windows.Forms.Panel ControlPanel;
        private System.Windows.Forms.Label TheLines;
        private System.Windows.Forms.Label LineLabel;
        private System.Windows.Forms.Label TheScore;
        private System.Windows.Forms.Label ScoerLabel;
        private System.Windows.Forms.Label NextLabel;
        private System.Windows.Forms.Label Preview;
        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.GroupBox groupBox2;
        private System.Windows.Forms.Label LevelLabel;
        private System.Windows.Forms.Label TheLevel;
        private System.Windows.Forms.Label GameStatus;

        /// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.TheGrid = new System.Windows.Forms.Panel();
            this.ControlPanel = new System.Windows.Forms.Panel();
            this.GameStatus = new System.Windows.Forms.Label();
            this.Preview = new System.Windows.Forms.Label();
            this.NextLabel = new System.Windows.Forms.Label();
            this.TheLines = new System.Windows.Forms.Label();
            this.LineLabel = new System.Windows.Forms.Label();
            this.TheScore = new System.Windows.Forms.Label();
            this.ScoerLabel = new System.Windows.Forms.Label();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.TheLevel = new System.Windows.Forms.Label();
            this.LevelLabel = new System.Windows.Forms.Label();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.ControlPanel.SuspendLayout();
            this.groupBox1.SuspendLayout();
            this.SuspendLayout();
            // 
            // TheGrid
            // 
            this.TheGrid.Dock = System.Windows.Forms.DockStyle.Left;
            this.TheGrid.Location = new System.Drawing.Point(0, 0);
            this.TheGrid.Name = "TheGrid";
            this.TheGrid.Padding = new System.Windows.Forms.Padding(1);
            this.TheGrid.Size = new System.Drawing.Size(238, 472);
            this.TheGrid.TabIndex = 0;
            this.TheGrid.Resize += new System.EventHandler(this.TheGrid_Resize);
            this.TheGrid.Paint += new System.Windows.Forms.PaintEventHandler(this.TheGrid_Paint);
            // 
            // ControlPanel
            // 
            this.ControlPanel.Controls.Add(this.GameStatus);
            this.ControlPanel.Controls.Add(this.Preview);
            this.ControlPanel.Controls.Add(this.NextLabel);
            this.ControlPanel.Controls.Add(this.TheLines);
            this.ControlPanel.Controls.Add(this.LineLabel);
            this.ControlPanel.Controls.Add(this.TheScore);
            this.ControlPanel.Controls.Add(this.ScoerLabel);
            this.ControlPanel.Controls.Add(this.groupBox1);
            this.ControlPanel.Controls.Add(this.groupBox2);
            this.ControlPanel.Location = new System.Drawing.Point(240, 0);
            this.ControlPanel.Name = "ControlPanel";
            this.ControlPanel.Padding = new System.Windows.Forms.Padding(1);
            this.ControlPanel.Size = new System.Drawing.Size(264, 472);
            this.ControlPanel.TabIndex = 1;
            this.ControlPanel.Resize += new System.EventHandler(this.ControlPanel_Resize);
            this.ControlPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.ControlPanel_Paint);
            // 
            // GameStatus
            // 
            this.GameStatus.AutoSize = true;
            this.GameStatus.Cursor = System.Windows.Forms.Cursors.Hand;
            this.GameStatus.Font = new System.Drawing.Font("Tahoma", 9.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.GameStatus.ForeColor = System.Drawing.Color.Red;
            this.GameStatus.Location = new System.Drawing.Point(5, 184);
            this.GameStatus.Name = "GameStatus";
            this.GameStatus.Size = new System.Drawing.Size(124, 16);
            this.GameStatus.TabIndex = 13;
            this.GameStatus.Text = "Start a New Game";
            this.GameStatus.Click += new System.EventHandler(this.GameStatus_Click);
            // 
            // Preview
            // 
            this.Preview.Location = new System.Drawing.Point(21, 297);
            this.Preview.Name = "Preview";
            this.Preview.Size = new System.Drawing.Size(87, 80);
            this.Preview.TabIndex = 10;
            this.Preview.Paint += new System.Windows.Forms.PaintEventHandler(this.Preview_Paint);
            // 
            // NextLabel
            // 
            this.NextLabel.AutoSize = true;
            this.NextLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.NextLabel.ForeColor = System.Drawing.Color.Gold;
            this.NextLabel.Location = new System.Drawing.Point(32, 264);
            this.NextLabel.Name = "NextLabel";
            this.NextLabel.Size = new System.Drawing.Size(49, 20);
            this.NextLabel.TabIndex = 9;
            this.NextLabel.Text = "Next :";
            this.NextLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // TheLines
            // 
            this.TheLines.AutoSize = true;
            this.TheLines.Font = new System.Drawing.Font("Stencil", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.TheLines.ForeColor = System.Drawing.Color.GreenYellow;
            this.TheLines.Location = new System.Drawing.Point(92, 68);
            this.TheLines.Name = "TheLines";
            this.TheLines.Size = new System.Drawing.Size(18, 19);
            this.TheLines.TabIndex = 8;
            this.TheLines.Text = "0";
            this.TheLines.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // LineLabel
            // 
            this.LineLabel.AutoSize = true;
            this.LineLabel.Font = new System.Drawing.Font("Stencil", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.LineLabel.ForeColor = System.Drawing.Color.GreenYellow;
            this.LineLabel.Location = new System.Drawing.Point(12, 68);
            this.LineLabel.Name = "LineLabel";
            this.LineLabel.Size = new System.Drawing.Size(53, 19);
            this.LineLabel.TabIndex = 7;
            this.LineLabel.Text = "Lines";
            this.LineLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // TheScore
            // 
            this.TheScore.AutoSize = true;
            this.TheScore.Font = new System.Drawing.Font("Stencil", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.TheScore.ForeColor = System.Drawing.Color.GreenYellow;
            this.TheScore.Location = new System.Drawing.Point(92, 28);
            this.TheScore.Name = "TheScore";
            this.TheScore.Size = new System.Drawing.Size(18, 19);
            this.TheScore.TabIndex = 6;
            this.TheScore.Text = "0";
            this.TheScore.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // ScoerLabel
            // 
            this.ScoerLabel.AutoSize = true;
            this.ScoerLabel.Font = new System.Drawing.Font("Stencil", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.ScoerLabel.ForeColor = System.Drawing.Color.GreenYellow;
            this.ScoerLabel.Location = new System.Drawing.Point(12, 28);
            this.ScoerLabel.Name = "ScoerLabel";
            this.ScoerLabel.Size = new System.Drawing.Size(57, 19);
            this.ScoerLabel.TabIndex = 5;
            this.ScoerLabel.Text = "Score";
            this.ScoerLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.TheLevel);
            this.groupBox1.Controls.Add(this.LevelLabel);
            this.groupBox1.ForeColor = System.Drawing.Color.Blue;
            this.groupBox1.Location = new System.Drawing.Point(5, 12);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(120, 140);
            this.groupBox1.TabIndex = 11;
            this.groupBox1.TabStop = false;
            // 
            // TheLevel
            // 
            this.TheLevel.AutoSize = true;
            this.TheLevel.Font = new System.Drawing.Font("Stencil", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.TheLevel.ForeColor = System.Drawing.Color.GreenYellow;
            this.TheLevel.Location = new System.Drawing.Point(87, 96);
            this.TheLevel.Name = "TheLevel";
            this.TheLevel.Size = new System.Drawing.Size(18, 19);
            this.TheLevel.TabIndex = 10;
            this.TheLevel.Text = "1";
            this.TheLevel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // LevelLabel
            // 
            this.LevelLabel.AutoSize = true;
            this.LevelLabel.Font = new System.Drawing.Font("Stencil", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.LevelLabel.ForeColor = System.Drawing.Color.GreenYellow;
            this.LevelLabel.Location = new System.Drawing.Point(9, 96);
            this.LevelLabel.Name = "LevelLabel";
            this.LevelLabel.Size = new System.Drawing.Size(55, 19);
            this.LevelLabel.TabIndex = 9;
            this.LevelLabel.Text = "Level";
            this.LevelLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // groupBox2
            // 
            this.groupBox2.Location = new System.Drawing.Point(5, 252);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(123, 144);
            this.groupBox2.TabIndex = 12;
            this.groupBox2.TabStop = false;
            // 
            // GamePanel
            // 
            this.Controls.Add(this.ControlPanel);
            this.Controls.Add(this.TheGrid);
            this.Name = "GamePanel";
            this.Size = new System.Drawing.Size(504, 472);
            this.ControlPanel.ResumeLayout(false);
            this.ControlPanel.PerformLayout();
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            this.ResumeLayout(false);

		}
		#endregion

        #region Private Functions
        /// <summary>
        /// Draw the various panels
        /// </summary>
        private void DrawPanels()
        {
            // Set the game panel size
            //----------------------------
            TheGame.UpdateSize();
            TheGrid.Width = TheGame.Width + 2;
            TheGrid.Height = TheGame.Height + 2;
            //----------------------------

            //Set the size of the control panels
            //----------------------------
            ControlPanel.Width = 190;
            ControlPanel.Height = TheGrid.Height;
            ControlPanel.Location = new Point(TheGrid.Width, 0);
            //----------------------------

            // Set the size of the complete control
            //----------------------------
            Width = TheGrid.Width + ControlPanel.Width + 4;
            Height = TheGrid.Height;
            //----------------------------

            // Repaint the control
            Refresh();
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Steps to be taken when the game starts
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
		private void TheGame_StartGame(object sender, EventArgs e)
		{
            // Initialize the scores 
            //------------------------
			TheScore.Text = "0";
			TheLines.Text = "0";
			TheLevel.Text = "1";
            //------------------------

            // The status 
            GameStatus.Text = TheGame.StatusString;

            // And we need the user to focus on the game panel
			TheGame.Focus();
		}

        /// <summary>
        /// Renders the next block on the preview screen
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
		private void TheGame_NextBlockMade(object sender, EventArgs e)
		{
            // Show the next piece in the preview
			Preview.Invalidate();
		}

        /// <summary>
        /// Keeps the score and line count
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
		private void TheGame_NewBlockMade(object sender, EventArgs e)
		{
            // Update the control panels
            //---------------------------------
			int temp = TheGame.Score;
			TheScore.Text = temp.ToString();
			temp = TheGame.Lines;
			TheLines.Text = temp.ToString();
			temp = TheGame.Level;
			TheLevel.Text = temp.ToString();
			GameStatus.Text = TheGame.StatusString;
            //---------------------------------
		}

        /// <summary>
        /// Renders the control
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
		private void ControlPanel_Paint(object sender, PaintEventArgs e)
		{
            // Border the panel
            //-----------------------------------
			e.Graphics.DrawLine(new Pen(Color.Red), 0, 0, ControlPanel.Width-1, 0);
			e.Graphics.DrawLine(new Pen(Color.Red), ControlPanel.Width-1, 0, ControlPanel.Width-1, ControlPanel.Height-1);
			e.Graphics.DrawLine(new Pen(Color.Red), 0,ControlPanel.Height-1, ControlPanel.ClientRectangle.Width-1, ControlPanel.Height-1);
            //-----------------------------------
		}

        /// <summary>
        /// Manages the size of the control panel
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
		private void ControlPanel_Resize(object sender, EventArgs e)
		{
            // The width is always 130... no resizing allowed :D
			ControlPanel.Width = 130;
		}

        /// <summary>
        /// Renders the grid
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
		private void TheGrid_Paint(object sender, PaintEventArgs e)
		{
            // Draw the border for the panel
			e.Graphics.DrawRectangle(new Pen(Color.Red), 0, 0, TheGrid.Width-1, TheGrid.Height-1);
		}

        /// <summary>
        /// Sizes the grid according to the window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
		private void TheGrid_Resize(object sender, EventArgs e)
		{
            // The game-grid always has its width and height stuck with the game's width and height
			TheGrid.Width = TheGame.Width + 2;
			TheGrid.Height = TheGame.Height + 2;
		}

        /// <summary>
        /// Renders the preview screen
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
		private void Preview_Paint(object sender, PaintEventArgs e)
		{
            // Check that the game is in progress
			if(TheGame.GameStart && !TheGame.GameEnd)
			{
                // Check what type the next block should be of depending on the random generation
				switch(TheGame.NextBlock)
				{
					case 0:
						new SquareBlock(TheGame).Preview(e.Graphics);
						break;
					case 1:
						new LShapedBlock(TheGame).Preview(e.Graphics);
						break;
					case 2:
						new GammaShapedBlock(TheGame).Preview(e.Graphics);
						break;
					case 3:
						new IShapedBlock(TheGame).Preview(e.Graphics);
						break;
					case 4:
						new SBlock(TheGame).Preview(e.Graphics);
						break;
					case 5:
						new ZBlock(TheGame).Preview(e.Graphics);
						break;
					case 6:
						new TBlock(TheGame).Preview(e.Graphics);
						break;						
				}
			}
			else
				e.Graphics.Clear(BackColor);
		}

        /// <summary>
        /// Steps to be taken to end a game
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
		private void TheGame_EndGame(object sender, EventArgs e)
		{
            // Paint the preview screen to blank
            Preview.Invalidate();
        }
        
        /// <summary>
        /// Handles the click on the current status of the game
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GameStatus_Click(object sender, EventArgs e)
        {
            if (!TheGame.GameStart)
                TheGame.InitializeNewGame();

            else TheGame.GamePause();
            Invalidate();
           
        }
        #endregion
    }
    #endregion
}